<?php

namespace App\Http\Controllers\Api;

use App\Models\ParkInfo;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use DB;

class ParkMonitorController extends AppBaseController
{
    public function getParkPreview()
    {
        return $this->sendResponse(collect($this->_getPreviewData())->sortBy('sort_by')->toArray(), 'success');
    }

    public function getParkPreviewWithParkCode($park_code)
    {
        $data = collect($this->_getPreviewData())->where('park_code', $park_code)->toArray();
        shuffle($data);
        return $this->sendResponse(
           $data,
           'success'
        );
    }

    private function _getPreviewData() {
        return $this->_createParkPreviewData(
            $this->_combineParkData(
                $this->_getParkBaseData(),
                $this->_getDevicesStatus(),
                $this->_getArmHeartBeat()
            )
        );
    }

    public function getParkDetail($park_code)
    {
        if (empty($park_code)) {
            return $this->sendApiError('park_code参数不能为空');
        }

        $parkData = collect(
            $this->_combineParkData(
                $this->_getParkBaseData(),
                $this->_getDevicesStatus(),
                $this->_getArmHeartBeat()
            ))
            ->where('park_code', $park_code)
            ->toArray();

        return $this->sendResponse($this->_createParkDetailData($parkData, obj2arr($this->_getConfigCloudDevice())), 'success');
    }

    private function _createParkDetailData($parkData, $cloudDeviceData)
    {
        foreach ($parkData as $parkKey => $park) {
            if (!empty($park['device_status'])) {
                foreach ($park['device_status'] as $deviceKey => $device) {
                    $parkData[$parkKey]['device_status'][$deviceKey]['disk_status'] = $this->_getDevicesDiskStatus($device);
                    $parkData[$parkKey]['device_status'][$deviceKey]['cpu_status'] = $this->_getDevicesCpuStatus($device);
                    $factory = $this->getFactoryName(
                        $this->getDeviceAttr($device, $cloudDeviceData, 'factory')
                    );

                    $gate_way = $this->getGateWayName(
                        $this->getDeviceAttr($device, $cloudDeviceData, 'gate_type')
                    );
                    $parkData[$parkKey]['device_status'][$deviceKey]['device_unique_id'] = $device['park_code'] .
                        $device['arm_code'] . $device['device_id'] . $device['factory'];
                    $parkData[$parkKey]['device_status'][$deviceKey]['other_data'] = $factory . '/' . $gate_way . '/' . $device['arm_code'];
                    // 这里有BUG

                    $parkData[$parkKey]['device_status'][$deviceKey]['owner_data'] = isset(obj2arr($this->getAirPortDevice())[$device['park_code']]) ?
                        collect(obj2arr($this->getAirPortDevice())[$device['park_code']])->where('device_id', $parkData[$parkKey]['device_status'][$deviceKey]['device_unique_id'])->toArray() :
                        '';
                        
                }
            }

        }
        shuffle($parkData);
        return $parkData;
    }

    private function getDeviceAttr($device, $data, $only)
    {
    
        foreach ($data[$device['park_code']] as $key => $value) {
            if (
               $value['park_code'] == $device['park_code'] && $value['arm_code'] == $device['arm_code'] &&
               $value['device_id'] == $device['device_id'] && $value['factory'] == $device['factory']
           ) {
                return $value[$only];
            }
        }
    }

    private function getFactoryName($type)
    {
        switch ($type) {
            case 0 : 
                $name = '艾润';
                break;
            case 1 : 
                $name = 'ETC';
                break;
            case 2 : 
                $name = '海康';
                break;   
            default :
                $name = '未知'; 
                    
        }
        return $name;
    }


    private function getGateWayName($type)
    {
        switch ($type) {
            case 1 : 
                $name = '入口';
                break;
            case 2 : 
                $name = '出口';
                break;   
            default :
                $name = '未知'; 
        }
        return $name;
    }


    private function _getDevicesCpuStatus($deviceStatus)
    {
        $statusArray = json_decode($deviceStatus['status'], true);
        if (!isset($statusArray['cpu'])) {
            return '';
        }
        // 3000 是CPU 瞬间的频率
        if (isset($statusArray['cpu']) && $statusArray['cpu'] > 3000) {
            return 'abnormal';
        } else {
            return 'normal';
        }
    }

    private function _getDevicesDiskStatus($deviceStatus)
    {
        $statusArray = json_decode($deviceStatus['status'], true);
        if (!isset($statusArray['disk'])) {
            return '';
        }
        if (isset($statusArray['disk']) && $statusArray['disk'] > 80) {
            return 'abnormal';
        }

        return 'normal';
    }
    private function _getDevicesNetStatus($deviceStatus)
    {
        $statusArray = json_decode($deviceStatus['status'], true);
        if (!isset($statusArray['network'])) {
            return false;
        }
        if (isset($statusArray['network']) != 1) {
            return false;
        } else {
            return true;
        }
    }
    private function _getDevicesCount($deviceStatus)
    {
        $statusArray = json_decode($deviceStatus['status'], true);
        if (!isset($statusArray['count'])) {
            return 0;
        }
        return $statusArray['count'];
    }

    private function getArmHeartBeat($item)
    {
        if (empty($item)) {
            return false;
        } else {
            // 大于2分半 就是有问题的
            if ((time() - $item['update_time']) > 150) {
                return false;
            }
            return true;
        }
    }

    private function decodeDevicesStatus($deviceStatus)
    {
        foreach ($deviceStatus as $key => $item) {
            $deviceStatus[$key]['status'] =  json_decode($item['status'], true);
        }
        return $deviceStatus;
    }

    private function _createParkPreviewData($parkData)
    {
        return collect($parkData)->map(function ($park) {
            if (!empty($park['arm_heartbeat'])) {
                if (!$this->checkArmHeartBeat($park['arm_heartbeat'])) {
                    $park['arm_status'] = 'abnormal';
                } else {
                    $park['arm_status'] = 'normal';
                }
            } else {
                $park['arm_status'] = 'abnormal';
            }

            if (!empty($park['device_status'])) {
                if (!$this->checkDevicesStatus($park['device_status'])) {
                    $park['device_state'] = 'abnormal';
                    $park['device_heartbeat'] = false;
                } else {
                    $park['device_state'] = 'normal';
                    $park['device_heartbeat'] = true;
                }
            } else {
                $park['device_state'] = false;
                $park['device_heartbeat'] = false;
            }
            $park['device_count'] = is_array($park['device_status'])?count($park['device_status']):0;
            $park['disk_status'] = $this->checkDevicesDiskStatus($park['device_status']);
            $park['cpu_status'] = $this->checkDevicesCpuStatus($park['device_status']);

            unset($park['device_status'], $park['arm_heartbeat']);
            return $park;
        })->toArray();
    }

    private function checkArmHeartBeat($heartBeat)
    {
        if (empty($heartBeat)) {
            return false;
        } else {
            foreach ($heartBeat as $item) {
                // 大于2分半 就是有问题的
                if ((time() - $item['update_time']) > 150) {
                    return false;
                }
            }
            return true;
        }
    }

    private function checkDevicesStatus($deviceStatus)
    {
        if (empty($deviceStatus)) {
            return false;
        } else {
            foreach ($deviceStatus as $item) {
                $statusArray = json_decode($item['status'], true);
                if ($statusArray['state'] != 0) {
                    return false;
                }
            }
            return true;
        }
    }

    private function checkDevicesCpuStatus($deviceStatus)
    {
        if (empty($deviceStatus)) {
            return false;
        }

        foreach ($deviceStatus as $item) {
            $statusArray = json_decode($item['status'], true);
            // 3000 是CPU 瞬间的频率
            if (!isset($statusArray['cpu']) || $statusArray['cpu'] > 3000) {
                return false;
            } else {
                return true;
            }
        }
        return true;
    }


    private function checkDevicesDiskStatus($deviceStatus)
    {
        if (empty($deviceStatus)) {
            return false;
        }

        foreach ($deviceStatus as $item) {
            $statusArray = json_decode($item['status'], true);
            if (!isset($statusArray['disk']) || $statusArray['disk'] > 80) {
                return false;
            } else {
                return true;
            }
        }
        return true;
    }

    private function getDevicesStatus($deviceStatus)
    {
        foreach ($deviceStatus as $item) {
            $statusArray = json_decode($item['status'], true);
            if ($statusArray['state'] != 0) {
                return false;
            }
        }
        return true;
    }
    private function _getSelfStatus($deviceStatus)
    {
        if($deviceStatus) {
            $statusArray = json_decode($deviceStatus['status'], true);
            switch ($deviceStatus['type']) {
                case 5 :  //arm
                    if ($statusArray['state'] == 1) {
                        return true;
                    }
                    break;
                case 7 : // 票箱
                    if ($statusArray['state'] == 1) {
                        return true;
                    }
                    break;
                case 2 : // 识别仪
                    if ($statusArray['state'] == 1) {
                        return true;
                    }
                    break;
                case 1 : // 道闸
                    if (in_array($statusArray['state'],[1,2,4])) {
                        return true;
                    }
                    break;
                case 3 : // 打印机
                    if ($statusArray['state'] == 1) {
                        return true;
                    }
                    break;
                case 6 : // 扫码器
                    break;
                default :
                    $name = '未知';
            }

        }
        return false;
    }


    private function _combineParkData($parks, $devices, $heartBeat, $deviceConf = [])
    {
        // 合并设备状态信息
        return collect($parks)->map(function ($park) use ($devices, $heartBeat, $deviceConf) {
            // 合并设备状态
            if (isset($devices[$park['park_code']])) {
                $park['device_status'] = obj2arr($devices[$park['park_code']]);
            } else {
                $park['device_status'] = '';
            }

            // 合并设备状态心跳
            if (isset($heartBeat[$park['park_code']])) {
                $park['arm_heartbeat'] = obj2arr($heartBeat[$park['park_code']]);
            } else {
                $park['arm_heartbeat'] = '';
            }
            return $park;
        })->toArray();
    }


    private function _getParkBaseData()
    {
        // 根据park_code 获取车场基础信息
        return ParkInfo::whereIn('park_code', $this->_getParksCode())
            ->select('park_code', 'parking_type','type_code', 'space_total', 'space_empty', 'parking_name', 'sort_by')
            ->orderBy("sort_by")
            ->get()
            ->toArray();
    }

    private function _getConfigCloudDevice()
    {
        // 获取Cloud Config下的 Device
        return DB::table('t_park_device')
            ->whereIn('park_code', $this->_getParksCode())
            ->select('park_code', 'arm_code', 'type', 'device_name', 'gate_type', 'factory', 'device_id')
            ->get()
            ->groupBy('park_code')
            ->toArray();
    }

    private function _getArmHeartBeat()
    {
        // 检测车场心跳
        return DB::connection('config_cloud')
            ->table('t_park_channel')
            ->whereIn('park_code', $this->_getParksCode())
            ->select('park_code', 'arm_code', 'update_time', 'channel_name')
            ->get()
            ->groupBy('park_code')
            ->toArray();
    }

    private function _getDevicesStatus()
    {
        // 获取车场下的设备状态
        return DB::table('t_arm_device_status')
            ->whereIn('park_code', $this->_getParksCode())
            ->where("type",5)
            ->get()
            ->groupBy('park_code')
            ->toArray();
    }

    private function _getParksCode()
    {
        return parent::getUserParks()
            ->keys()
            ->toArray();
    }

    private function getAirPortDevice()
    {
        // 获取车场下的设备状态
        return DB::table('devices')
            ->where('deleted_at', '=', NULL)
            ->whereIn('park_code', $this->_getParksCode())
            ->get()
            ->groupBy('park_code')
            ->toArray();
    }

    /**
     * 1：道闸，2:识别仪，3：打印机，4：显示屏，5：控制器,6：扫码器,7:票箱
     *
     * @param $park_code
     * @return mixed
     */
    public function deviceList($park_code){
        if(empty($park_code)){
            return $this->sendError('缺少车场ID');
        }
        $park_arr[] = $park_code;
        // 获取车场下的设备状态
        $arm_info = DB::table('t_arm_device_status')
            ->whereIn('park_code', $park_arr)
//            ->where('status', "not like", '%state":0%')
            ->orderBy('type','desc')
            ->get()
            ->groupBy('type')
            ->toArray();

        $data = collect([]);
        // arm  5
        if(isset($arm_info[5])){
            $data = collect($arm_info)->map(function($val,$key){
                $ret = [];
                $i = 0;
                foreach ($val as $k=>$v) {
                    // 判断这个设备是否存在
                    $exist_data = DB::table("park_channels")->where("park_code",$v->park_code)
                        ->where("arm_code",$v->arm_code)
                        ->value("arm_code");
                    if(empty($exist_data)) {
                        unset($val[$k]);
                        continue;
                    }
                    $device_info = DB::table('t_park_device')
                        ->where("park_code",$v->park_code)
                        ->where("arm_code",$v->arm_code)
                        ->where("factory",$v->factory)
                        ->where("device_id",$v->device_id)
                        ->select(["gate_type","device_name"])
                        ->first();

                    $v->device_unique_id = $v->park_code.$v->arm_code.$v->device_id.$v->factory;
                    $v->device_name = $device_info->device_name??'';
                    $v->gate_type = $device_info->gate_type??'';
                    $v->postion = $device_info->postion??'';
                    $v->update_time = $v->update;
                    $v->update = $v->update ? date("Y-m-d H:i:s",$v->update):'';
                    $v->brand = $this->getFactoryName($v->factory);
                    $v->gate_type = $this->getGateWayName($v->gate_type);
                    $item = obj2arr($v);
                    $v->device_status = $this->_getSelfStatus($item);
                    switch ($v->type) {
                        case 5 :  //arm
                            $v->disk_status = $this->_getDevicesDiskStatus($item);
                            $v->cpu_status = $this->_getDevicesCpuStatus($item);
                            $v->heartbeat = $this->getArmHeartBeat($item);
                            break;
                        case 7 : // 票箱
                            $v->net_status = $this->_getDevicesNetStatus($item);
                            break;
                        case 2 : // 识别仪
                            $statusArray = json_decode($item['status'], true);
                            if (isset($statusArray['state']) && $statusArray['state']==0) {
                                unset($val[$k]);
                            }
                            $v->mysql_status = '';
                            break;
                        case 1 : // 道闸
                            $v->lift_count = $this->_getDevicesCount($item);
                            $v->device_status = $this->_getSelfStatus($item);
                            break;
                        case 3 : // 打印机
                            $v->net_status = $this->_getDevicesNetStatus($item);
                            break;
                        case 6 : // 扫码器
                            break;
                        default :
                            $name = '未知';
                    }
                    $ret[$i] = $v;
                    $i ++;
                }
                return $ret;
            })->toArray();
        }
        unset($data[0]);
        return $this->sendResponse($data, 'success');
    }

}
